package com.jxtc.enterprise.common.utils;

import com.jxtc.enterprise.common.exception.HttpClientException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;

/**
 * HTTP 客户端工具类，基于 RestTemplate 封装。
 * 提供 GET、POST、PUT、DELETE 请求的便捷调用，支持自定义请求头、参数及异常处理。
 */
@Component
public class HttpClientUtil {

    private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    private final RestTemplate restTemplate;

    public HttpClientUtil(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * 通用 HTTP 请求封装（支持泛型类型，如 List<T>）
     *
     * @param url          请求地址
     * @param method       HTTP 方法
     * @param headersMap   请求头
     * @param requestBody  请求体（GET/DELETE 可为空）
     * @param responseType 响应类型引用，用于复杂泛型（如：new ParameterizedTypeReference<Result<User>>() {}）
     * @param uriVariables URL 参数
     * @return T 响应实体
     */
    public <T> T exchange(String url, HttpMethod method, Map<String, String> headersMap,
                          Object requestBody, ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables) {
        return executeExchange(url, method, headersMap, requestBody, responseType, uriVariables);
    }

    /**
     * 通用 HTTP 请求封装（支持简单类型，如 String、Integer 等）
     *
     * @param url          请求地址
     * @param method       HTTP 方法
     * @param headersMap   请求头
     * @param requestBody  请求体（GET/DELETE 可为空）
     * @param responseType 响应类型 Class 对象（如 String.class、User.class）
     * @param uriVariables URL 参数
     * @return T 响应实体
     */
    public <T> T exchange(String url, HttpMethod method, Map<String, String> headersMap,
                          Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        return executeExchange(url, method, headersMap, requestBody, responseType, uriVariables);
    }

    @SuppressWarnings("unchecked")
    private <T> T executeExchange(String url, HttpMethod method, Map<String, String> headersMap,
                                  Object requestBody, Object responseType, Map<String, ?> uriVariables) {
        // 检查 URL 和 HTTP 方法是否为空
        if (Objects.isNull(url) || Objects.isNull(method)) {
            throw new IllegalArgumentException("请求 URL 和 HTTP 方法不能为空");
        }

        try {
            // 构建 HTTP 头部
            HttpHeaders headers = new HttpHeaders();
            // 设置 content-type 为 JSON
            headers.setContentType(MediaType.APPLICATION_JSON);
            if (headersMap != null) {
                headersMap.forEach(headers::set);
            }

            // 构建请求实体
            HttpEntity<Object> entity = new HttpEntity<>(requestBody, headers);

            // 处理 uriVariables 为空的情况，避免 RestTemplate 报错
            Map<String, ?> safeUriVariables = (uriVariables != null) ? uriVariables : Collections.emptyMap();

            // 根据响应类型选择 exchange 方法
            if (responseType instanceof ParameterizedTypeReference) {
                ParameterizedTypeReference<T> typeRef = (ParameterizedTypeReference<T>) responseType;
                ResponseEntity<T> response = restTemplate.exchange(url, method, entity, typeRef, safeUriVariables);
                return response.getBody();
            } else if (responseType instanceof Class) {
                Class<T> clazz = (Class<T>) responseType;
                ResponseEntity<T> response = restTemplate.exchange(url, method, entity, clazz, safeUriVariables);
                return response.getBody();
            } else {
                throw new IllegalArgumentException("不支持的响应类型，仅接受 ParameterizedTypeReference 或 Class");
            }
        } catch (HttpStatusCodeException e) {
            logger.error("HTTP 错误: [{}] {}, 状态码: {}, 响应体: {}", method, url, e.getStatusCode(), e.getResponseBodyAsString());
            throw new HttpClientException("请求失败，HTTP 状态码: " + e.getStatusCode(), e);
        } catch (ResourceAccessException e) {
            logger.error("请求超时: [{}] {}, 错误信息: {}", method, url, e.getMessage());
            throw new HttpClientException("请求超时：" + e.getMessage(), e);
        } catch (RestClientException e) {
            logger.error("请求异常: [{}] {}, 错误信息: {}", method, url, e.getMessage());
            throw new HttpClientException("请求异常：" + e.getMessage(), e);
        }
    }


    /**
     * 发送 GET 请求
     *
     * @param url          请求地址
     * @param headers      请求头
     * @param responseType 响应类型
     * @param uriVariables URL 参数
     * @return T 响应实体
     */
    public <T> T get(String url, Map<String, String> headers, ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables) {
        return exchange(url, HttpMethod.GET, headers, null, responseType, uriVariables);
    }

    public <T> T get(String url, Map<String, String> headers, Class<T> responseType, Map<String, ?> uriVariables) {
        return exchange(url, HttpMethod.GET, headers, null, responseType, uriVariables);
    }

    /**
     * 发送 GET 请求（无 Header 及 URL 参数）
     *
     * @param url          请求地址，请求参数手动拼接
     * @param responseType 响应类型
     * @return T 响应实体
     */
    public <T> T get(String url, ParameterizedTypeReference<T> responseType) {
        return get(url, null, responseType, null);
    }

    public <T> T get(String url, Class<T> responseType) {
        return get(url, null, responseType, null);
    }

    /**
     * 发送 POST 请求
     *
     * @param url          请求地址
     * @param headers      请求头
     * @param requestBody  请求体
     * @param responseType 响应类型
     * @return T 响应实体
     */
    public <T> T post(String url, Map<String, String> headers, Object requestBody, ParameterizedTypeReference<T> responseType) {
        return exchange(url, HttpMethod.POST, headers, requestBody, responseType, null);
    }

    public <T> T post(String url, Map<String, String> headers, Object requestBody, Class<T> responseType) {
        return exchange(url, HttpMethod.POST, headers, requestBody, responseType, null);
    }

    /**
     * 发送 PUT 请求
     *
     * @param url         请求地址
     * @param headers     请求头
     * @param requestBody 请求体
     */
    public void put(String url, Map<String, String> headers, Object requestBody) {
        exchange(url, HttpMethod.PUT, headers, requestBody, Void.class, null);
    }

    public <T> T put(String url, Map<String, String> headers, Object requestBody, ParameterizedTypeReference<T> responseType) {
        return exchange(url, HttpMethod.PUT, headers, requestBody, responseType, null);
    }

    /**
     * 发送 DELETE 请求
     *
     * @param url          请求地址
     * @param headers      请求头
     * @param uriVariables URL 参数
     */
    public void delete(String url, Map<String, String> headers, Map<String, ?> uriVariables) {
        exchange(url, HttpMethod.DELETE, headers, null, Void.class, uriVariables);
    }

    public <T> T delete(String url, Map<String, String> headers, ParameterizedTypeReference<T> responseType) {
        return exchange(url, HttpMethod.DELETE, headers, null, responseType, null);
    }

    public <T> T delete(String url, Map<String, String> headers, Map<String, ?> uriVariables, ParameterizedTypeReference<T> responseType) {
        return exchange(url, HttpMethod.DELETE, headers, null, responseType, uriVariables);
    }
}
